home *** CD-ROM | disk | FTP | other *** search
- #include "util.h"
- #include "mmdf.h"
-
- /*
- * MULTI-CHANNEL MEMO DISTRIBUTION FACILITY (MMDF)
- *
- *
- * Copyright (C) 1979,1980,1981 University of Delaware
- *
- * Department of Electrical Engineering
- * University of Delaware
- * Newark, Delaware 19711
- *
- * Phone: (302) 738-1163
- *
- *
- * This program module was developed as part of the University
- * of Delaware's Multi-Channel Memo Distribution Facility (MMDF).
- *
- * Acquisition, use, and distribution of this module and its listings
- * are subject restricted to the terms of a license agreement.
- * Documents describing systems using this module must cite its source.
- *
- * The above statements must be retained with all copies of this
- * program and may not be removed without the consent of the
- * University of Delaware.
- *
- *
- * version -1 David H. Crocker March 1979
- * version 0 David H. Crocker April 1980
- * version v7 David H. Crocker May 1981
- * version 1 David H. Crocker October 1981
- *
- */
- /* SEND FROM PHONE TO LOCAL (SUBMIT) */
-
- #include "ch.h"
- #include "phs.h"
- #include "ph.h"
-
- extern char *getline();
- extern char *index();
- extern char *rindex();
- extern char *malloc();
-
- char *sender = 0; /* address of mail sender */
-
- #define BUFL 600 /* length of buf */
- char buf[BUFL]; /* general usage */
- char netbuf[BUFL]; /* the place that has the valid characters */
- int netcount = 0; /* number of valid characters in netbuf */
- char *netptr = netbuf; /* next character to come out of netbuf */
- char *arg; /* zero if no argument - pts to comm param */
- int numrecipients = 0; /* number of valid recipients accepted */
- char *addrfix();
- int doneflag = 0;
-
- /* character defines */
- #define CNULL '\0' /* null */
-
-
- /****************************************************************
- * *
- * C O M M A N D D I S P A T C H T A B L E *
- * *
- ****************************************************************/
-
- int helo(), mail(), quit(), help(), rcpt(), accept();
- int data(), rset(), reject(), turn();
-
- struct comarr /* format of the command table */
- {
- char *cmdname; /* ascii name */
- int (*cmdfunc)(); /* command procedure to call */
- } commands[] = {
- "helo", helo, "noop", accept,
- "mail", mail, "data", data,
- "rcpt", rcpt, "help", help,
- "send", mail, "quit", quit,
- "saml", mail, "soml", reject,
- "vrfy", reject, "expn", reject,
- "rset", rset, "turn", turn,
- NULL, NULL
- };
-
- extern LLog *logptr;
- extern struct ps_rstruct ps_rp;
- extern char *supportaddr;
- extern Chan *curchan;
-
- LOCVAR long msglen;
- LOCVAR int numadrs;
-
- ph2mm_send (curchan) /* overall mngmt for batch of msgs */
- Chan *curchan; /* who to say is doing relaying */
- {
- short result;
- char *i;
- char info[LINESIZE],
- sender[LINESIZE];
- register struct comarr *comp;
-
- #ifdef DEBUG
- ll_log (logptr, LLOGPTR, "ph2mm_send");
- #endif
-
- if (rp_isbad (result = ph_pkinit ()))
- {
- printx ("remote site refuses to send mail...\n");
- fflush (stdout);
- return (result);
- }
- if (rp_isbad (result = mm_sbinit ()))
- return (result);
-
- printx ("starting to pickup mail...\n");
- fflush (stdout);
-
- nextcomm:
- while (i = getline())
- {
- if (i == (char *)NOTOK) /* handle error ??? */
- return(byebye( 1 ));
-
- /* find and call command procedure */
- comp = commands;
- while( comp->cmdname != NULL) /* while there are names */
- {
- if (strcmp(buf, comp->cmdname) == 0) /* a winner */
- {
- /* call comm proc */
- result = (*comp->cmdfunc)();
- if (doneflag) /* set by byebye */
- return(result);
- goto nextcomm; /* back for more */
- }
- comp++; /* bump to next candidate */
- }
- netreply("500 I never heard of that command before" );
- }
- return(byebye(0));
- }
-
- /*name:
- getline
-
- function:
- get commands from the standard input terminated by <cr><lf>.
- afix a pointer( arg ) to any arguments passed.
- ignore carriage returns
- map UPPER case to lower case.
- manage the netptr and netcount variables
-
- algorithm:
- while we havent received a line feed and buffer not full
-
- if netcount is zero or less
- get more data from net
- error: return 0
- check for delimiter character
- null terminate first string
- set arg pointer to next character
- check for carriage return
- ignore it
- if looking at command name
- convert upper case to lower case
-
- if command line (not mail)
- null terminate last token
- manage netptr
-
- returns:
- 0 for EOF
- -1 when an error occurs on network connection
- ptr to last character (null) in command line
-
- globals:
- netcount=
- netptr =
- buf=
- */
-
- char *
- getline()
- {
- register char *inp; /* input pointer in netbuf */
- register char *outp; /* output pointer in buf */
- register int c; /* temporary char */
- extern char *progname;
-
- inp = netptr;
- outp = buf;
- arg = 0;
-
- if (rp_isbad (ph_rrec(netbuf, &netcount)))
- {
- ll_log( logptr, LLOGTMP, "net input read error");
- return((char *)NOTOK);
- }
- inp = netbuf;
- do
- {
- c = *inp++ & 0377;
- if (c == '\r' || /* ignore CR */
- c >= 0200) /* or any telnet codes that */
- continue; /* try to sneak through */
- if (arg == NULL)
- {
- /* if char is a delim afix token */
- if (c == ' ' || c == ',')
- {
- c = CNULL; /* make null term'ed */
- arg = outp + 1; /* set arg ptr */
- }
- else if (c >= 'A' && c <= 'Z')
- /* do case mapping (UPPER -> lower) */
- c += 'a' - 'A';
- }
- *outp++ = c;
- } while (netcount-- > 0 && outp < &buf[BUFL] );
-
- *--outp = 0; /* null term the last token */
-
- /* scan off blanks in argument */
- if (arg) {
- while (*arg == ' ')
- arg++;
- if (*arg == '\0')
- arg = 0; /* if all blanks, no argument */
- }
- ll_log( logptr, LLOGFTR, "'%s', '%s'", buf,
- arg == 0 ? "<noarg>" : arg );
-
- /* reset netptr for next trip in */
- netptr = inp;
- /* return success */
- return (outp);
- }
-
- /*
- * Process the HELO command
- */
- helo()
- {
- char replybuf[128];
-
- if (curchan -> ch_confstr)
- sprintf (replybuf, "250 %s", curchan -> ch_confstr);
- else
- sprintf (replybuf, "250 %s.%s", curchan -> ch_lname,
- curchan -> ch_ldomain);
- netreply (replybuf);
- }
-
- /*
- * mail
- *
- * handle the MAIL command ("MAIL from:<user@host>")
- */
- mail()
- {
- int result;
- char *cp;
- char info[40];
- char replybuf[256];
- struct rp_bufstruct thereply;
- int len;
-
- if (arg == 0) {
- netreply("501 No argument supplied");
- return;
- } else if( sender ) {
- netreply("503 MAIL command already accepted");
- return;
- } else if (!equal(arg, "from:", 5)) {
- netreply("501 No sender named");
- return;
- }
-
- if (equal(buf, "mail", 4))
- strcpy (info, "mv");
- else if (equal(buf, "send", 4))
- strcpy (info, "yv");
- else if (equal(buf, "saml", 4))
- strcpy (info, "bv");
- else
- strcpy (info, "mv"); /* shouldn't ever get here */
-
- /* Scan FROM: parts of arg */
- sender = index (arg, ':') + 1;
- sender = addrfix( sender );
-
- /* Supply necessary flags, "tiCHANNEL" will be supplied by winit */
- if (*sender == NULL) {
- strcat( info, "q"); /* No return mail */
- sender = "Orphanage"; /* Placeholder */
- }
-
- if( rp_isbad( mm_winit(curchan -> ch_name, info, sender))) {
- netreply("451 Temporary problem initializing");
- sender = (char *) 0;
- mm_end( NOTOK );
- mmdfstart();
- } else if( rp_isbad( mm_rrply( &thereply, &len ))) {
- netreply( "451 Temporary problem initializing" );
- sender = (char *) 0;
- mm_end( NOTOK );
- mmdfstart();
- } else if( rp_gbval( thereply.rp_val ) == RP_BNO) {
- sprintf (replybuf, "501 %s", thereply.rp_line);
- netreply (replybuf);
- sender = (char *) 0;
- mm_end( NOTOK );
- mmdfstart();
- } else if( rp_gbval( thereply.rp_val ) == RP_BTNO) {
- sprintf (replybuf, "451 %s", thereply.rp_line);
- netreply (replybuf);
- sender = (char *) 0;
- mm_end( NOTOK );
- mmdfstart();
- } else
- netreply("250 OK");
- numrecipients = 0;
- }
-
- /*
- * Process the RCPT command ("RCPT TO:<forward-path>")
- */
- rcpt()
- {
- register char *p;
- struct rp_bufstruct thereply;
- char replybuf[256];
- int len;
-
- /* parse destination arg */
- if( sender == (char *)0 ) {
- netreply("503 You must give a MAIL command first");
- return;
- } else if (arg == (char *)0 || !equal(arg, "to:", 3)) {
- netreply("501 No recipient named.");
- return;
- }
- p = index( arg, ':' ) + 1;
- p = addrfix( p );
-
- if( rp_isbad( mm_wadr( (char *)0, p ))) {
- if( rp_isbad( mm_rrply( &thereply, &len )))
- netreply( "451 Mail system problem" );
- else {
- sprintf (replybuf, "451 %s", thereply.rp_line);
- netreply (replybuf);
- }
- } else {
- if( rp_isbad( mm_rrply( &thereply, &len )))
- netreply("451 Mail system problem");
- else if( rp_gbval( thereply.rp_val ) == RP_BNO) {
- sprintf (replybuf, "550 %s", thereply.rp_line);
- netreply (replybuf);
- }
- else if( rp_gbval( thereply.rp_val ) == RP_BTNO) {
- sprintf (replybuf, "451 %s", thereply.rp_line);
- netreply (replybuf);
- }
- else {
- netreply("250 Recipient OK.");
- numrecipients++;
- }
- }
- }
-
- /*
- * ADDRFIX() -- This function takes the SMTP "path" and removes
- * the leading and trailing "<>"'s which would make the address
- * illegal to RFC822 mailers. Note that although the spec states
- * that the angle brackets are required, we will accept addresses
- * without them. (DPK@BRL, 4 Jan 83)
- */
- char *
- addrfix( addrp )
- char *addrp;
- {
- register char *cp;
-
- if( cp = index( addrp, '<' )) {
- addrp = ++cp;
- if( cp = rindex( addrp, '>' ))
- *cp = 0;
- }
- compress (addrp, addrp);
- #ifdef DEBUG
- ll_log( logptr, LLOGFTR, "addrfix(): '%s'", addrp );
- #endif
- return( addrp );
- }
-
- /*
- * Process the DATA command. Send text to MMDF.
- */
- data()
- {
- int werrflg;
- struct rp_bufstruct thereply;
- int len;
- int result;
-
- werrflg = 0;
- if (numrecipients == 0) {
- netreply("503 No recipients have been specified.");
- return;
- }
-
- if( rp_isbad(mm_waend())) {
- netreply("451 Unknown mail system trouble.");
- return;
- }
-
- netreply ("354 Enter Mail, end by a line with only '.'");
-
- #ifdef DEBUG
- ll_log( logptr, LLOGFTR, "... body of message ..." );
- #endif
- printx ("receiving...:");
- fflush (stdout);
-
- len = BUFL;
- while ((rp_gval (result = ph_rstm (buf, &len))) == RP_OK)
- {
- printx (".");
- fflush (stdout);
-
- /* If write error occurs, stop writing but keep reading. */
- if (!werrflg)
- if (rp_isbad (result = mm_wtxt (buf, len))) {
- werrflg++;
- ll_log( logptr, LLOGTMP, "error from submit");
- }
-
- len = BUFL;
- }
- #ifdef DEBUG
- ll_log( logptr, LLOGBTR, "Finished receiving text." );
- #endif
- if (rp_isbad(result)) {
- ll_log (logptr, LLOGTMP, "error reading text");
- printx("\n\terror reading text\n");
- fflush(stdout);
- return(byebye( 1 ));
- }
-
- if (werrflg) {
- netreply("451-Mail trouble (write error to mailsystem)");
- netreply("451 Please try again later.");
- return(byebye( 1 ));
- }
-
- printx(" "); /* keep it pretty */
- fflush(stdout);
-
- /* slurp up the end-of-text dot (we knew we were done anyway) */
- len = BUFL;
- if (rp_isbad(ph_rrec(buf, &len))) {
- ll_log(logptr, LLOGTMP, "error reading '.'");
- printx("\n\terror reading '.'\n");
- fflush(stdout);
- return(byebye( 1 ));
- }
-
- if( rp_isbad(mm_wtend()) || rp_isbad( mm_rrply( &thereply, &len)))
- netreply("451 Unknown mail trouble, try later");
- else if( rp_isgood(thereply.rp_val)) {
- sprintf (buf, "250 %s", thereply.rp_line);
- netreply (buf);
- }
- else if( rp_gbval(thereply.rp_val) == RP_BNO) {
- sprintf (buf, "554 %s", thereply.rp_line);
- netreply (buf);
- }
- else {
- sprintf (buf, "451 %s", thereply.rp_line);
- netreply (buf);
- }
- sender = (char *) 0;
- numrecipients = 0;
- }
-
- /*
- * Process the TURN command
- */
- turn()
- {
- accept();
- return(byebye(3)); /* pass the turn message upstairs */
- }
-
- /*
- * Process the RSET command
- */
- rset()
- {
- mm_end( NOTOK );
- sender = (char *)0;
- mmdfstart();
- accept();
- }
-
- mmdfstart()
- {
- if( rp_isbad( mm_init() ) || rp_isbad( mm_sbinit() )) {
- ll_log( logptr, LLOGFAT, "can't reinitialize mail system" );
- netreply("421 Server can't initialize mail system (mmdf)");
- return(byebye( 2 ));
- }
- numrecipients = 0;
- }
-
- /*
- * handle the QUIT command
- */
- quit()
- {
- char buf[128];
- time_t timenow;
-
- time (&timenow);
- sprintf (buf, "221 session complete at %.19s.",
- ctime(&timenow));
- netreply(buf);
- return(byebye( 0 ));
- }
-
- byebye( retval )
- int retval;
- {
- doneflag++;
- switch (retval)
- {
- case 0:
- mm_sbend();
- mm_end(OK);
- return(RP_DONE);
- case 1:
- mm_end (NOTOK);
- return (RP_BTNO);
- case 2:
- mm_end (NOTOK);
- return (RP_NO);
- case 3:
- mm_sbend();
- mm_end(OK);
- return(RP_OK); /* signal that we should turn line around */
- }
- }
-
- /*
- * Reply that the current command has been logged and noted
- */
- accept()
- {
- netreply("250 OK");
- }
-
- /*
- * Tell other side that we don't support a command.
- */
- reject()
- {
- netreply("502 Command not implemented.");
- }
-
- /*
- * Process the HELP command by giving a list of valid commands
- */
- help()
- {
- /* register i; */
- /* register struct comarr *p; */
- char replybuf[256];
-
- /* netreply("214-The following commands are accepted:\r\n214-" );
- * for(p = commands, i = 1; p->cmdname; p++, i++) {
- * sprintf (replybuf, "%s%s", p->cmdname, ((i%10)?" ":"\r\n214-") );
- * netreply (replybuf);
- * }
- */
- sprintf (replybuf, "214 Send complaints/bugs to: %s", supportaddr);
- netreply (replybuf);
- }
-
- /*
- * Send appropriate ascii responses over the network connection.
- */
-
- netreply(string)
- char *string;
- {
- int len;
-
- if (rp_isbad( ph_wrec(string, strlen(string)))) {
- ll_log( logptr, LLOGFST,
- "(netreply) error in writing [%s] ...",
- string);
- return(byebye( 1 ));
- }
- #ifdef DEBUG
- ll_log( logptr, LLOGFTR, "%s", string);
- #endif DEBUG
- }
-